package com.common.server.common.util;

import com.common.server.common.exception.CustomerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.UUID;

/**
 * 描述：文件处理工具类
 * <p>
 * 作者：HuTongFu
 * 时间：2019/6/25 10:58
 */
public class FileUtil {

    private static Logger logger = LoggerFactory.getLogger(FileUtil.class);

    /**
     * 根据文件code组装文件url
     */
    public static String fileUrlConvert(String fileCode) {
        return fileUrlConvert(IPUtils.getLocalURI(), fileCode);
    }

    /**
     * 根据ip和文件code组装文件url
     */
    public static String fileUrlConvert(String ip, String code) {
        if (StringUtils.isBlank(ip) || StringUtils.isBlank(code)) {
            logger.info("ip 或者 code 为空");
            return null;
        }
        return ip + "/file/download/" + code;
    }

    /**
     * 上传文件
     *
     * @param file     文件
     * @param filePath 文件路径
     * @param fileName
     * @throws Exception
     */
    public static String uploadFile(MultipartFile file, String filePath, String fileName) throws Exception {
        String fileCode = FileType.fileType(fileName) + System.currentTimeMillis();
        File targetFile = new File(filePath + fileName);
        // 检测是否存在目录
        if (!targetFile.getParentFile().exists()) {
            // 新建文件夹
            targetFile.getParentFile().mkdirs();
        }
        // 文件写入
        file.transferTo(targetFile);
        return fileCode;
    }

    /**
     * 下载文件
     *
     * @param file     文件
     * @param response 输出
     */
    public static void downloadFile(File file, HttpServletResponse response) throws IOException {
        byte[] buffer = new byte[1024];
        //获取文件输入流
        FileInputStream fis = new FileInputStream(file);
        //获取文件输入到response 的输出流
        OutputStream os = response.getOutputStream();
        int len;
        while ((len = fis.read(buffer)) > 0) {
            os.write(buffer, 0, len);
        }
        fis.close();
        if (os != null) {
            os.flush();
            os.close();
        }
    }

    /**
     * 根据文件删除文件
     *
     * @param param 文件
     * @return boolean
     */
    public static boolean deleteFile(String param) {
        File file = new File(param);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            return file.delete();
        } else {
            return false;
        }

    }

    /**
     * 循环删除文件
     *
     * @param path
     * @return
     */
    public static void deleteCycleFile(String path) {

        File file = new File(path);
        if (!file.exists()) {
            throw new CustomerException("文件不存在!");
        }
        if (!file.isDirectory()) {
            deleteFile(file.getAbsolutePath());
        } else {
            File[] files = file.listFiles();
            if (files == null || files.length == 0) {
                throw new CustomerException("文件夹是空的!");
            } else {
                for (File file2 : files) {
                    if (file2.isDirectory()) {
                        deleteCycleFile(file2.getAbsolutePath());
                    } else {
                        deleteFile(file2.getAbsolutePath());
                    }
                }
            }
        }
    }

    public static String renameToUUID(String fileName) {
        return UUID.randomUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * 保存文件
     *
     * @param inputStream
     * @param fileName
     * @param filePath
     */
    public static String saveFile(InputStream inputStream, String fileName, String filePath) {

        OutputStream os = null;

        try {
            byte[] bs = new byte[1024 * 10];
            int len;
            File tempFile = new File(filePath);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            fileName = System.currentTimeMillis() + fileName;
            os = new FileOutputStream(tempFile.getPath() + File.separator + fileName);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (Exception e) {
            logger.error("保存文件失败!!!", e);
        } finally {
            // 完毕，关闭所有链接
            try {
                Objects.requireNonNull(os).flush();
                Objects.requireNonNull(os).close();
                inputStream.close();
            } catch (IOException e) {
                logger.error("关闭文件流链接失败!!!", e);
            }
        }
        return fileName;
    }

    /**
     * 从文件中读取内容返回字符串
     *
     * @param filePath 文件全路径
     * @return
     */
    public static String readfile(String filePath) {
        File file = new File(filePath);
        StringBuilder buffer = new StringBuilder();
        try {
            InputStream inputStream = new FileInputStream(file);
            byte[] bytes = new byte[1024];
            int n;
            while ((n = inputStream.read(bytes)) != -1) {
                buffer.append(new String(bytes, 0, n, StandardCharsets.UTF_8));
            }
        } catch (IOException e) {
            logger.error("文件读取异常!!!", e);
        }
        return buffer.toString();
    }

    /**
     * 将文件转为 base64 格式
     *
     * @param imageFile
     * @param formatName
     * @return
     */
    public static String encodeFileToBase64(File imageFile, String formatName) {// 将文件转化为字节数组字符串，并对其进行Base64编码处理
        ByteArrayOutputStream outputStream = null;
        try {
            BufferedImage bufferedImage = ImageIO.read(imageFile);
            outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, formatName, outputStream);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return Base64Utils.encode(outputStream != null ? outputStream.toByteArray() : new byte[0]);// 返回Base64编码过的字节数组字符串
    }
}
